package com.xinchuang.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.fill.FillConfig;
import com.alibaba.excel.write.metadata.fill.FillWrapper;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.xinchuang.comment.KeyWord;
import com.xinchuang.comment.R;
import com.xinchuang.config.CellMergeWriterHandler;
import com.xinchuang.config.CustomTemplateSheetStrategy;
import com.xinchuang.domain.pojo.TryOutDeviceMod;
import com.xinchuang.domain.vo.inner.*;
import com.xinchuang.mapper.TryOutDeviceModMapper;
import com.xinchuang.service.ExportInnerQuotationService;
import com.xinchuang.service.IMoldSelectionService;
import com.xinchuang.utils.BigdecimalUtil;
import com.xinchuang.utils.DateUtils;
import com.xinchuang.utils.EasyExcelUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.compress.utils.Lists;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.util.CellRangeAddress;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;

import java.io.File;
import java.text.DecimalFormat;
import java.util.*;

/**
 * @Description:导出对内报价
 * @Author: thh
 * @Date: 2023/10/15 15:34
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class ExportInnerQuotationServiceImpl implements ExportInnerQuotationService {

    private final KeyWord keyWord;
    private final TryOutDeviceModMapper tryOutDeviceModMapper;

    @Autowired
    private IMoldSelectionService iMoldSelectionService;

    /**
     * 通用外部报价单导出
     *
     * @param data
     */
    @Override
    public String exportInnerOutQuotation(String data) {
        String rootUrl = keyWord.getFileUrl();
        String resultPath = "";
        try {
            R r = JSON.parseObject(data, R.class);
            ReqInnerQuoDetailsVO innerQuoDetailsVO = JSON.parseObject(JSON.toJSONString(r.getData()), ReqInnerQuoDetailsVO.class);
            String moldSelectionId = innerQuoDetailsVO.getMoldSelectionId();
            String projectName = iMoldSelectionService.getProjectName(moldSelectionId);
            resultPath = "file" + File.separator + projectName + "项目-目标价格表-" + DateUtils.dateTimeNow("yyyyMMdd-SSS") + ".xlsx";
            String filePath = rootUrl + File.separator + resultPath;
            List<Map<String, Object>> dataList = new ArrayList<>();
            DecimalFormat df2 = new DecimalFormat("0.00");
            DecimalFormat df3 = new DecimalFormat("0.000");
            List<InnerBaseInfo> innerBaseInfoList = innerQuoDetailsVO.getDataList();
            //合并单元格
            int size = innerBaseInfoList.size();
            List<CellRangeAddress> cellRangeAddresss = Lists.newArrayList();
            int firstRow = size + 3;
            //总价所在行合并单元格
            cellRangeAddresss.add(new CellRangeAddress(firstRow, firstRow, 12, 13));
            //汇总比所在行合并单元格
            cellRangeAddresss.add(new CellRangeAddress(firstRow + 1, firstRow + 1, 12, 13));
            for (int i = 0; i < size; i++) {
                firstRow = 3 + i;
                cellRangeAddresss.add(new CellRangeAddress(firstRow, firstRow, 12, 13));

                Map<String, Object> map = new HashMap<>();
                //初始化明细数据
                intMap(map);
                InnerBaseInfo innerBaseInfo = innerBaseInfoList.get(i);
                InnerBaseInfo innerBaseInfoNew = new InnerBaseInfo();
                BeanUtils.copyProperties(innerBaseInfo, innerBaseInfoNew);
                innerBaseInfoNew.setDetailData(null);
                map.putAll(BeanUtil.beanToMap(innerBaseInfoNew, false, false));
                map.put("assemblyFee", BigdecimalUtil.doubleTo2DecimalString(innerBaseInfo.getAssemblyFee()));
                map.put("boughtInComponents", BigdecimalUtil.doubleTo2DecimalString(innerBaseInfo.getBoughtInComponents()));
                map.put("finalTaxNotIncluded", BigdecimalUtil.doubleTo2DecimalString(innerBaseInfo.getFinalTaxNotIncluded()));
                map.put("heightOfProduct", BigdecimalUtil.doubleTo2DecimalString(innerBaseInfo.getHeightOfProduct()));
                map.put("hotRunnerAimFee", BigdecimalUtil.doubleTo2DecimalString(innerBaseInfo.getHotRunnerAimFee()));
                map.put("ironMaterialsFee", BigdecimalUtil.doubleTo2DecimalString(innerBaseInfo.getIronMaterialsFee()));
                map.put("lengthOfProduct", BigdecimalUtil.doubleTo2DecimalString(innerBaseInfo.getLengthOfProduct()));
                map.put("mainMaterialsFee", BigdecimalUtil.doubleTo2DecimalString(innerBaseInfo.getMainMaterialsFee()));
                map.put("manufacturingFee", BigdecimalUtil.doubleTo2DecimalString(innerBaseInfo.getManufacturingFee()));
                map.put("mouldFee", BigdecimalUtil.doubleTo2DecimalString(innerBaseInfo.getMouldFee()));
                map.put("outsourceFee", BigdecimalUtil.doubleTo2DecimalString(innerBaseInfo.getOutsourceFee()));
                map.put("periodRectificationFee", BigdecimalUtil.doubleTo2DecimalString(innerBaseInfo.getPeriodRectificationFee()));
                map.put("plasticMaterialAimFee", BigdecimalUtil.doubleTo2DecimalString(innerBaseInfo.getPlasticMaterialAimFee()));
                map.put("standardComponentFee", BigdecimalUtil.doubleTo2DecimalString(innerBaseInfo.getStandardComponentFee()));
                map.put("targetGrossProfit", BigdecimalUtil.doubleTo2DecimalString(innerBaseInfo.getTargetGrossProfit()));
                map.put("texturingAimFee", BigdecimalUtil.doubleTo2DecimalString(innerBaseInfo.getTexturingAimFee()));
                map.put("transportFee", BigdecimalUtil.doubleTo2DecimalString(innerBaseInfo.getTransportFee()));
                map.put("tryoutFee", BigdecimalUtil.doubleTo2DecimalString(innerBaseInfo.getTryoutFee()));
                map.put("widthOfProduct", BigdecimalUtil.doubleTo2DecimalString(innerBaseInfo.getWidthOfProduct()));
                //图片
                final String imageOfProduct = innerBaseInfo.getImageOfProduct();
                if (StringUtils.isNotEmpty(imageOfProduct)) {
                    map.put("imageFile", new File(rootUrl + File.separator + imageOfProduct));
                }
                //序号
                map.put("index", i + 1);
                //模具信息
                MoldInfo mouldInfo = innerBaseInfo.getDetailData().getMouldInfo();
                map.put("mouldInfo.lengthOfMould", BigdecimalUtil.doubleTo2DecimalString(mouldInfo.getLengthOfMould()));
                map.put("mouldInfo.widthOfMould", BigdecimalUtil.doubleTo2DecimalString(mouldInfo.getWidthOfMould()));
                map.put("mouldInfo.heightOfMould", BigdecimalUtil.doubleTo2DecimalString(mouldInfo.getHeightOfMould()));
                map.put("mouldInfo.count", BigdecimalUtil.doubleTo2DecimalString(mouldInfo.getCount()));
                map.put("mouldInfo.price", df2.format(mouldInfo.getPrice()));
                map.put("mouldInfo.totalPrice", df2.format(mouldInfo.getTotalPrice()));
                //装配费用类
                AssemblyFee assemblyFeeOfDetail = innerBaseInfo.getDetailData().getAssemblyFeeOfDetail();
                map.put("assemblyFee.num", assemblyFeeOfDetail.getNum());
                map.put("assemblyFee.price", df2.format(assemblyFeeOfDetail.getPrice()));
                map.put("assemblyFee.totalPrice", df2.format(assemblyFeeOfDetail.getTotalPrice()));
                //热流道
                HotRunner hotRunner = innerBaseInfo.getDetailData().getHotRunner();
                map.put("hotRunner.num", hotRunner.getNum());
                map.put("hotRunner.price", df2.format(hotRunner.getPrice()));
                map.put("hotRunner.totalPrice", df2.format(hotRunner.getTotalPrice()));
                //油缸费用
                OilCylinder oilCylinder = innerBaseInfo.getDetailData().getOilCylinder();
                map.put("oilCylinder.num", oilCylinder.getNum());
                map.put("oilCylinder.price", df2.format(oilCylinder.getPrice()));
                map.put("oilCylinder.totalPrice", df2.format(oilCylinder.getTotalPrice()));
                //水电油接头顶针的价格
                Double thimblePrice = innerBaseInfo.getDetailData().getThimblePrice();
                map.put("thimblePrice", df2.format(thimblePrice == null ? 0 : thimblePrice));
                //纹理价格
                TexturingCost texturingCost = innerBaseInfo.getDetailData().getTexturingCost();
                map.put("texturingCost.area", BigdecimalUtil.doubleTo2DecimalString(texturingCost.getArea()));
                map.put("texturingCost.price", df2.format(texturingCost.getPrice()));
                map.put("texturingCost.totalPrice", df2.format(texturingCost.getTotalPrice()));
                //塑料材料费用
                PlasticMaterialCost plasticMaterialCost = innerBaseInfo.getDetailData().getPlasticMaterialCost();
                map.put("plasticMaterialCost.weight", df3.format(plasticMaterialCost.getWeight()));
                map.put("plasticMaterialCost.price", df2.format(plasticMaterialCost.getPrice()));
                map.put("plasticMaterialCost.totalPrice", df2.format(plasticMaterialCost.getTotalPrice()));
                //运输费用 (费用详情中运输费用)
                Double transportFeeOfDetail = innerBaseInfo.getDetailData().getTransportFeeOfDetail();
                map.put("transportFeeOfDetail", df2.format(transportFeeOfDetail == null ? 0 : transportFeeOfDetail));
                //外购件-检具价格
                Double gagePrice = innerBaseInfo.getDetailData().getGagePrice();
                map.put("gagePrice", df2.format(gagePrice == null ? 0 : gagePrice));
                //外购件-石墨电极价格
                Double graphiteElectrodeCost = innerBaseInfo.getDetailData().getGraphiteElectrodeCost();
                map.put("graphiteElectrodeCost", df2.format(graphiteElectrodeCost == null ? 0 : graphiteElectrodeCost));
                //试模费用
                TryoutFee tryoutFee = innerBaseInfo.getDetailData().getTryoutFeeOfDetail();
                TryOutDeviceMod tryOutDeviceMod = tryOutDeviceModMapper.selectOne(new QueryWrapper<TryOutDeviceMod>().lambda().eq(TryOutDeviceMod::getDeviceId, tryoutFee.getDeviceId()));
                if (Objects.nonNull(tryOutDeviceMod)) {
                    map.put("tryoutFee.deviceName", tryOutDeviceMod.getDeviceName());
                }
                map.put("tryoutFee.hour", tryoutFee.getHour());
                map.put("tryoutFee.price", df2.format(tryoutFee.getPrice()));
                map.put("tryoutFee.totalPrice", df2.format(tryoutFee.getTotalPrice()));

                //零件
                List<MoldPart> moldPartList = innerBaseInfo.getDetailData().getMoldPartList();
                if (Objects.nonNull(moldPartList) && !moldPartList.isEmpty()) {
                    Optional<MoldPart> moldPartA = moldPartList.stream().filter(moldPart -> moldPart.getPartName().equals("A板")).findFirst();
                    if (moldPartA.isPresent()) {
                        MoldPart moldPart = moldPartA.get();
                        map.put("moldPartA.lengthOfPart", BigdecimalUtil.doubleTo2DecimalString(moldPart.getLengthOfPart()));
                        map.put("moldPartA.widthOfPart", BigdecimalUtil.doubleTo2DecimalString(moldPart.getWidthOfPart()));
                        map.put("moldPartA.heightOfPart", BigdecimalUtil.doubleTo2DecimalString(moldPart.getHeightOfPart()));
                        map.put("moldPartA.densityOfPart", BigdecimalUtil.doubleTo7DecimalString(moldPart.getDensityOfPart()));
                        map.put("moldPartA.weightOfPart", df3.format(moldPart.getWeightOfPart()));
                        map.put("moldPartA.countOfPart", moldPart.getCountOfPart());
                        map.put("moldPartA.priceOfPart", df2.format(moldPart.getPriceOfPart()));
                        map.put("moldPartA.totalPrice", df2.format(moldPart.getTotalPrice()));
                        map.put("moldPartA.manufacturingFee", df2.format(moldPart.getManufacturingFee()));
                    }
                    Optional<MoldPart> moldPartB = moldPartList.stream().filter(moldPart -> moldPart.getPartName().equals("B板")).findFirst();
                    if (moldPartB.isPresent()) {
                        MoldPart moldPart = moldPartB.get();
                        map.put("moldPartB.lengthOfPart", BigdecimalUtil.doubleTo2DecimalString(moldPart.getLengthOfPart()));
                        map.put("moldPartB.widthOfPart", BigdecimalUtil.doubleTo2DecimalString(moldPart.getWidthOfPart()));
                        map.put("moldPartB.heightOfPart", BigdecimalUtil.doubleTo2DecimalString(moldPart.getHeightOfPart()));
                        map.put("moldPartB.densityOfPart", BigdecimalUtil.doubleTo7DecimalString(moldPart.getDensityOfPart()));
                        map.put("moldPartB.weightOfPart", df3.format(moldPart.getWeightOfPart()));
                        map.put("moldPartB.countOfPart", moldPart.getCountOfPart());
                        map.put("moldPartB.priceOfPart", df2.format(moldPart.getPriceOfPart()));
                        map.put("moldPartB.totalPrice", df2.format(moldPart.getTotalPrice()));
                        map.put("moldPartB.manufacturingFee", df2.format(moldPart.getManufacturingFee()));
                    }
                    Optional<MoldPart> moldPartDzd = moldPartList.stream().filter(moldPart -> moldPart.getPartName().equals("大直顶")).findFirst();
                    if (moldPartDzd.isPresent()) {
                        MoldPart moldPart = moldPartDzd.get();
                        map.put("moldPartDzd.lengthOfPart", BigdecimalUtil.doubleTo2DecimalString(moldPart.getLengthOfPart()));
                        map.put("moldPartDzd.widthOfPart", BigdecimalUtil.doubleTo2DecimalString(moldPart.getWidthOfPart()));
                        map.put("moldPartDzd.heightOfPart", BigdecimalUtil.doubleTo2DecimalString(moldPart.getHeightOfPart()));
                        map.put("moldPartDzd.densityOfPart", BigdecimalUtil.doubleTo7DecimalString(moldPart.getDensityOfPart()));
                        map.put("moldPartDzd.weightOfPart", df3.format(moldPart.getWeightOfPart()));
                        map.put("moldPartDzd.countOfPart", moldPart.getCountOfPart());
                        map.put("moldPartDzd.priceOfPart", df2.format(moldPart.getPriceOfPart()));
                        map.put("moldPartDzd.totalPrice", df2.format(moldPart.getTotalPrice()));
                        map.put("moldPartDzd.manufacturingFee", df2.format(moldPart.getManufacturingFee()));
                        map.put("moldPartDzd.totalStandardComponentCost", df2.format(moldPart.getTotalStandardComponentCost()));
                    }
                    Optional<MoldPart> moldPartDxj = moldPartList.stream().filter(moldPart -> moldPart.getPartName().equals("大镶件")).findFirst();
                    if (moldPartDxj.isPresent()) {
                        MoldPart moldPart = moldPartDxj.get();
                        map.put("moldPartDxj.lengthOfPart", BigdecimalUtil.doubleTo2DecimalString(moldPart.getLengthOfPart()));
                        map.put("moldPartDxj.widthOfPart", BigdecimalUtil.doubleTo2DecimalString(moldPart.getWidthOfPart()));
                        map.put("moldPartDxj.heightOfPart", BigdecimalUtil.doubleTo2DecimalString(moldPart.getHeightOfPart()));
                        map.put("moldPartDxj.densityOfPart", BigdecimalUtil.doubleTo7DecimalString(moldPart.getDensityOfPart()));
                        map.put("moldPartDxj.weightOfPart", df3.format(moldPart.getWeightOfPart()));
                        map.put("moldPartDxj.countOfPart", moldPart.getCountOfPart());
                        map.put("moldPartDxj.priceOfPart", df2.format(moldPart.getPriceOfPart()));
                        map.put("moldPartDxj.totalPrice", df2.format(moldPart.getTotalPrice()));
                        map.put("moldPartDxj.manufacturingFee", df2.format(moldPart.getManufacturingFee()));
                    }
                    Optional<MoldPart> moldPartDgm = moldPartList.stream().filter(moldPart -> moldPart.getPartName().equals("大盖帽")).findFirst();
                    if (moldPartDgm.isPresent()) {
                        MoldPart moldPart = moldPartDgm.get();
                        map.put("moldPartDgm.lengthOfPart", BigdecimalUtil.doubleTo2DecimalString(moldPart.getLengthOfPart()));
                        map.put("moldPartDgm.widthOfPart", BigdecimalUtil.doubleTo2DecimalString(moldPart.getWidthOfPart()));
                        map.put("moldPartDgm.heightOfPart", BigdecimalUtil.doubleTo2DecimalString(moldPart.getHeightOfPart()));
                        map.put("moldPartDgm.densityOfPart", BigdecimalUtil.doubleTo7DecimalString(moldPart.getDensityOfPart()));
                        map.put("moldPartDgm.weightOfPart", df3.format(moldPart.getWeightOfPart()));
                        map.put("moldPartDgm.countOfPart", moldPart.getCountOfPart());
                        map.put("moldPartDgm.priceOfPart", df2.format(moldPart.getPriceOfPart()));
                        map.put("moldPartDgm.totalPrice", df2.format(moldPart.getTotalPrice()));
                        map.put("moldPartDgm.manufacturingFee", df2.format(moldPart.getManufacturingFee()));
                        map.put("moldPartDgm.totalStandardComponentCost", df2.format(moldPart.getTotalStandardComponentCost()));
                    }
                    Optional<MoldPart> moldPartDxd = moldPartList.stream().filter(moldPart -> moldPart.getPartName().equals("大斜顶")).findFirst();
                    if (moldPartDxd.isPresent()) {
                        MoldPart moldPart = moldPartDxd.get();
                        map.put("moldPartDxd.lengthOfPart", BigdecimalUtil.doubleTo2DecimalString(moldPart.getLengthOfPart()));
                        map.put("moldPartDxd.widthOfPart", BigdecimalUtil.doubleTo2DecimalString(moldPart.getWidthOfPart()));
                        map.put("moldPartDxd.heightOfPart", BigdecimalUtil.doubleTo2DecimalString(moldPart.getHeightOfPart()));
                        map.put("moldPartDxd.densityOfPart", BigdecimalUtil.doubleTo7DecimalString(moldPart.getDensityOfPart()));
                        map.put("moldPartDxd.weightOfPart", df3.format(moldPart.getWeightOfPart()));
                        map.put("moldPartDxd.countOfPart", moldPart.getCountOfPart());
                        map.put("moldPartDxd.priceOfPart", df2.format(moldPart.getPriceOfPart()));
                        map.put("moldPartDxd.totalPrice", df2.format(moldPart.getTotalPrice()));
                        map.put("moldPartDxd.manufacturingFee", df2.format(moldPart.getManufacturingFee()));
                        map.put("moldPartDxd.totalStandardComponentCost", df2.format(moldPart.getTotalStandardComponentCost()));
                    }
                    Optional<MoldPart> moldPartDhk = moldPartList.stream().filter(moldPart -> moldPart.getPartName().equals("大滑块")).findFirst();
                    if (moldPartDhk.isPresent()) {
                        MoldPart moldPart = moldPartDhk.get();
                        map.put("moldPartDhk.lengthOfPart", BigdecimalUtil.doubleTo2DecimalString(moldPart.getLengthOfPart()));
                        map.put("moldPartDhk.widthOfPart", BigdecimalUtil.doubleTo2DecimalString(moldPart.getWidthOfPart()));
                        map.put("moldPartDhk.heightOfPart", BigdecimalUtil.doubleTo2DecimalString(moldPart.getHeightOfPart()));
                        map.put("moldPartDhk.densityOfPart", BigdecimalUtil.doubleTo7DecimalString(moldPart.getDensityOfPart()));
                        map.put("moldPartDhk.weightOfPart", df3.format(moldPart.getWeightOfPart()));
                        map.put("moldPartDhk.countOfPart", moldPart.getCountOfPart());
                        map.put("moldPartDhk.priceOfPart", df2.format(moldPart.getPriceOfPart()));
                        map.put("moldPartDhk.totalPrice", df2.format(moldPart.getTotalPrice()));
                        map.put("moldPartDhk.manufacturingFee", df2.format(moldPart.getManufacturingFee()));
                        map.put("moldPartDhk.totalStandardComponentCost", df2.format(moldPart.getTotalStandardComponentCost()));
                    }
                    Optional<MoldPart> moldPartDtk = moldPartList.stream().filter(moldPart -> moldPart.getPartName().equals("推块（大斜顶上的）")).findFirst();
                    if (moldPartDtk.isPresent()) {
                        MoldPart moldPart = moldPartDtk.get();
                        map.put("moldPartDtk.lengthOfPart", BigdecimalUtil.doubleTo2DecimalString(moldPart.getLengthOfPart()));
                        map.put("moldPartDtk.widthOfPart", BigdecimalUtil.doubleTo2DecimalString(moldPart.getWidthOfPart()));
                        map.put("moldPartDtk.heightOfPart", BigdecimalUtil.doubleTo2DecimalString(moldPart.getHeightOfPart()));
                        map.put("moldPartDtk.densityOfPart", BigdecimalUtil.doubleTo7DecimalString(moldPart.getDensityOfPart()));
                        map.put("moldPartDtk.weightOfPart", df3.format(moldPart.getWeightOfPart()));
                        map.put("moldPartDtk.countOfPart", moldPart.getCountOfPart());
                        map.put("moldPartDtk.priceOfPart", df2.format(moldPart.getPriceOfPart()));
                        map.put("moldPartDtk.totalPrice", df2.format(moldPart.getTotalPrice()));
                        map.put("moldPartDtk.manufacturingFee", df2.format(moldPart.getManufacturingFee()));
                        map.put("moldPartDtk.totalStandardComponentCost", df2.format(moldPart.getTotalStandardComponentCost()));
                    }
                }
                //小刚料
                List<IronMaterial> ironMaterialList = innerBaseInfo.getDetailData().getIronMaterialList();
                if (Objects.nonNull(ironMaterialList) && !ironMaterialList.isEmpty()) {
                    Optional<IronMaterial> ironMaterialXxd = ironMaterialList.stream().filter(ironMaterial -> ironMaterial.getIronMaterialsName().equals("小斜顶")).findFirst();
                    if (ironMaterialXxd.isPresent()) {
                        IronMaterial ironMaterial = ironMaterialXxd.get();
                        map.put("ironMaterialXxd.count", ironMaterial.getCount());
                        map.put("ironMaterialXxd.price", df2.format(ironMaterial.getPrice()));
                        map.put("ironMaterialXxd.materialTotalPrice", df2.format(ironMaterial.getMaterialTotalPrice()));
                        map.put("ironMaterialXxd.processPrice", df2.format(ironMaterial.getProcessPrice()));
                        map.put("ironMaterialXxd.totalProcessPrice", df2.format(ironMaterial.getTotalProcessPrice()));
                        map.put("ironMaterialXxd.standardComponent", df2.format(ironMaterial.getStandardComponent()));
                        map.put("ironMaterialXxd.totalStandardComponentCost", df2.format(ironMaterial.getTotalStandardComponentCost()));
                    }
                    Optional<IronMaterial> ironMaterialXzd = ironMaterialList.stream().filter(ironMaterial -> ironMaterial.getIronMaterialsName().equals("小直顶")).findFirst();
                    if (ironMaterialXzd.isPresent()) {
                        IronMaterial ironMaterial = ironMaterialXzd.get();
                        map.put("ironMaterialXzd.count", ironMaterial.getCount());
                        map.put("ironMaterialXzd.price", df2.format(ironMaterial.getPrice()));
                        map.put("ironMaterialXzd.materialTotalPrice", df2.format(ironMaterial.getMaterialTotalPrice()));
                        map.put("ironMaterialXzd.processPrice", df2.format(ironMaterial.getProcessPrice()));
                        map.put("ironMaterialXzd.totalProcessPrice", df2.format(ironMaterial.getTotalProcessPrice()));
                        map.put("ironMaterialXzd.standardComponent", df2.format(ironMaterial.getStandardComponent()));
                        map.put("ironMaterialXzd.totalStandardComponentCost", df2.format(ironMaterial.getTotalStandardComponentCost()));
                    }
                    Optional<IronMaterial> ironMaterialtk = ironMaterialList.stream().filter(ironMaterial -> ironMaterial.getIronMaterialsName().equals("推块")).findFirst();
                    if (ironMaterialtk.isPresent()) {
                        IronMaterial ironMaterial = ironMaterialtk.get();
                        map.put("ironMaterialtk.count", ironMaterial.getCount());
                        map.put("ironMaterialtk.price", df2.format(ironMaterial.getPrice()));
                        map.put("ironMaterialtk.materialTotalPrice", df2.format(ironMaterial.getMaterialTotalPrice()));
                        map.put("ironMaterialtk.processPrice", df2.format(ironMaterial.getProcessPrice()));
                        map.put("ironMaterialtk.totalProcessPrice", df2.format(ironMaterial.getTotalProcessPrice()));
                        map.put("ironMaterialtk.standardComponent", df2.format(ironMaterial.getStandardComponent()));
                        map.put("ironMaterialtk.totalStandardComponentCost", df2.format(ironMaterial.getTotalStandardComponentCost()));
                    }
                }
                dataList.add(map);
            }


            TotalFee totalFeeOfAll = innerQuoDetailsVO.getTotalFeeOfAll();
            Map<String, Object> totalFeeOfAllMap = BeanUtil.beanToMap(totalFeeOfAll, false, false);
            totalFeeOfAllMap.put("tryoutTimesTotal", innerBaseInfoList.stream()
                    .mapToInt(x -> Integer.valueOf(StringUtils.isNotBlank(x.getTryoutTimes()) ? x.getTryoutTimes() : "0")).sum());
            totalFeeOfAllMap.put("assemblyfeeTotal", BigdecimalUtil.doubleTo2DecimalString(totalFeeOfAll.getAssemblyfeeTotal()));
            totalFeeOfAllMap.put("boughtInComponentsTotal", BigdecimalUtil.doubleTo2DecimalString(totalFeeOfAll.getBoughtInComponentsTotal()));
            totalFeeOfAllMap.put("finalTaxNotIncludedTotal", BigdecimalUtil.doubleTo2DecimalString(totalFeeOfAll.getFinalTaxNotIncludedTotal()));
            totalFeeOfAllMap.put("hotRunnerAimFeeTotal", BigdecimalUtil.doubleTo2DecimalString(totalFeeOfAll.getHotRunnerAimFeeTotal()));
            totalFeeOfAllMap.put("ironMaterialsFeeTotal", BigdecimalUtil.doubleTo2DecimalString(totalFeeOfAll.getIronMaterialsFeeTotal()));
            totalFeeOfAllMap.put("mainMaterialsFeeTotal", BigdecimalUtil.doubleTo2DecimalString(totalFeeOfAll.getMainMaterialsFeeTotal()));
            totalFeeOfAllMap.put("manufacturingFeeTotal", BigdecimalUtil.doubleTo2DecimalString(totalFeeOfAll.getManufacturingFeeTotal()));
            totalFeeOfAllMap.put("mouldFeeTotal", BigdecimalUtil.doubleTo2DecimalString(totalFeeOfAll.getMouldFeeTotal()));
            totalFeeOfAllMap.put("outsourceFeeTotal", BigdecimalUtil.doubleTo2DecimalString(totalFeeOfAll.getOutsourceFeeTotal()));
            totalFeeOfAllMap.put("periodRectificationFeeTotal", BigdecimalUtil.doubleTo2DecimalString(totalFeeOfAll.getPeriodRectificationFeeTotal()));
            totalFeeOfAllMap.put("plasticMaterialAimFeeTotal", BigdecimalUtil.doubleTo2DecimalString(totalFeeOfAll.getPlasticMaterialAimFeeTotal()));
            totalFeeOfAllMap.put("standardComponentFeeTotal", BigdecimalUtil.doubleTo2DecimalString(totalFeeOfAll.getStandardComponentFeeTotal()));
            totalFeeOfAllMap.put("targetGrossProfitTotal", BigdecimalUtil.doubleTo2DecimalString(totalFeeOfAll.getTargetGrossProfitTotal()));
            totalFeeOfAllMap.put("texturingAimFeeTotal", BigdecimalUtil.doubleTo2DecimalString(totalFeeOfAll.getTexturingAimFeeTotal()));
            totalFeeOfAllMap.put("transportFeeTotal", BigdecimalUtil.doubleTo2DecimalString(totalFeeOfAll.getTransportFeeTotal()));
            totalFeeOfAllMap.put("tryoutFeeTotal", BigdecimalUtil.doubleTo2DecimalString(totalFeeOfAll.getTryoutFeeTotal()));
            //项目名称
            totalFeeOfAllMap.put("projectName", projectName);
            //汇总比
            totalFeeOfAllMap.put("mainMaterialsFeeTotalRate", BigdecimalUtil.bigDecimalToDivide(totalFeeOfAllMap.get("mainMaterialsFeeTotal"), totalFeeOfAllMap.get("finalTaxNotIncludedTotal")));
            totalFeeOfAllMap.put("mouldFeeTotalRate", BigdecimalUtil.bigDecimalToDivide(totalFeeOfAllMap.get("mouldFeeTotal"), totalFeeOfAllMap.get("finalTaxNotIncludedTotal")));
            totalFeeOfAllMap.put("ironMaterialsFeeTotalRate", BigdecimalUtil.bigDecimalToDivide(totalFeeOfAllMap.get("ironMaterialsFeeTotal"), totalFeeOfAllMap.get("finalTaxNotIncludedTotal")));
            totalFeeOfAllMap.put("standardComponentFeeTotalRate", BigdecimalUtil.bigDecimalToDivide(totalFeeOfAllMap.get("standardComponentFeeTotal"), totalFeeOfAllMap.get("finalTaxNotIncludedTotal")));
            totalFeeOfAllMap.put("outsourceFeeTotalRate", BigdecimalUtil.bigDecimalToDivide(totalFeeOfAllMap.get("outsourceFeeTotal"), totalFeeOfAllMap.get("finalTaxNotIncludedTotal")));
            totalFeeOfAllMap.put("hotRunnerAimFeeTotalRate", BigdecimalUtil.bigDecimalToDivide(totalFeeOfAllMap.get("hotRunnerAimFeeTotal"), totalFeeOfAllMap.get("finalTaxNotIncludedTotal")));
            totalFeeOfAllMap.put("boughtInComponentsTotalRate", BigdecimalUtil.bigDecimalToDivide(totalFeeOfAllMap.get("boughtInComponentsTotal"), totalFeeOfAllMap.get("finalTaxNotIncludedTotal")));
            totalFeeOfAllMap.put("texturingAimFeeTotalRate", BigdecimalUtil.bigDecimalToDivide(totalFeeOfAllMap.get("texturingAimFeeTotal"), totalFeeOfAllMap.get("finalTaxNotIncludedTotal")));
            totalFeeOfAllMap.put("plasticMaterialAimFeeTotalRate", BigdecimalUtil.bigDecimalToDivide(totalFeeOfAllMap.get("plasticMaterialAimFeeTotal"), totalFeeOfAllMap.get("finalTaxNotIncludedTotal")));
            totalFeeOfAllMap.put("assemblyfeeTotalRate", BigdecimalUtil.bigDecimalToDivide(totalFeeOfAllMap.get("assemblyfeeTotal"), totalFeeOfAllMap.get("finalTaxNotIncludedTotal")));
            totalFeeOfAllMap.put("tryoutFeeTotalRate", BigdecimalUtil.bigDecimalToDivide(totalFeeOfAllMap.get("tryoutFeeTotal"), totalFeeOfAllMap.get("finalTaxNotIncludedTotal")));
            totalFeeOfAllMap.put("transportFeeTotalRate", BigdecimalUtil.bigDecimalToDivide(totalFeeOfAllMap.get("transportFeeTotal"), totalFeeOfAllMap.get("finalTaxNotIncludedTotal")));
            totalFeeOfAllMap.put("manufacturingFeeTotalRate", BigdecimalUtil.bigDecimalToDivide(totalFeeOfAllMap.get("manufacturingFeeTotal"), totalFeeOfAllMap.get("finalTaxNotIncludedTotal")));
            totalFeeOfAllMap.put("periodRectificationFeeTotalRate", BigdecimalUtil.bigDecimalToDivide(totalFeeOfAllMap.get("periodRectificationFeeTotal"), totalFeeOfAllMap.get("finalTaxNotIncludedTotal")));


            try (ExcelWriter excelWriter = EasyExcel.write(filePath)
                    .inMemory(Boolean.TRUE)
                    .registerWriteHandler(EasyExcelUtil.getStyleStrategy())
                    .registerWriteHandler(new CustomTemplateSheetStrategy(0, projectName + "项目目标毛利润 "))
                    .registerWriteHandler(new CellMergeWriterHandler.MyMergeStrategy(cellRangeAddresss))
                    .withTemplate(getClass().getClassLoader().getResourceAsStream("templates/inner_quotation_template.xlsx"))
                    .build()) {
                WriteSheet writeSheet = EasyExcel.writerSheet(0).build();
                FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();
                excelWriter.fill(new FillWrapper("list", dataList), fillConfig, writeSheet);
                excelWriter.fill(totalFeeOfAllMap, fillConfig, writeSheet);
                excelWriter.fill(totalFeeOfAllMap, fillConfig, writeSheet);
                excelWriter.finish();
            }
            log.info("内部报价单导出成功");
        } catch (Exception e) {
            e.printStackTrace();
        }

        return resultPath;
    }

    /**
     * 放置默认值
     *
     * @param map
     */
    private void intMap(Map<String, Object> map) {
        map.put("moldPartA.lengthOfPart", "");
        map.put("moldPartA.widthOfPart", "");
        map.put("moldPartA.heightOfPart", "");
        map.put("moldPartA.densityOfPart", "");
        map.put("moldPartA.weightOfPart", "");
        map.put("moldPartA.countOfPart", "");
        map.put("moldPartA.priceOfPart", "");
        map.put("moldPartA.totalPrice", "");
        map.put("moldPartA.manufacturingFee", "");

        map.put("moldPartB.lengthOfPart", "");
        map.put("moldPartB.widthOfPart", "");
        map.put("moldPartB.heightOfPart", "");
        map.put("moldPartB.densityOfPart", "");
        map.put("moldPartB.weightOfPart", "");
        map.put("moldPartB.countOfPart", "");
        map.put("moldPartB.priceOfPart", "");
        map.put("moldPartB.totalPrice", "");
        map.put("moldPartB.manufacturingFee", "");

        map.put("moldPartDzd.lengthOfPart", "");
        map.put("moldPartDzd.widthOfPart", "");
        map.put("moldPartDzd.heightOfPart", "");
        map.put("moldPartDzd.densityOfPart", "");
        map.put("moldPartDzd.weightOfPart", "");
        map.put("moldPartDzd.countOfPart", "");
        map.put("moldPartDzd.priceOfPart", "");
        map.put("moldPartDzd.totalPrice", "");
        map.put("moldPartDzd.manufacturingFee", "");
        map.put("moldPartDzd.totalStandardComponentCost", "");

        map.put("moldPartDxj.lengthOfPart", "");
        map.put("moldPartDxj.widthOfPart", "");
        map.put("moldPartDxj.heightOfPart", "");
        map.put("moldPartDxj.densityOfPart", "");
        map.put("moldPartDxj.weightOfPart", "");
        map.put("moldPartDxj.countOfPart", "");
        map.put("moldPartDxj.priceOfPart", "");
        map.put("moldPartDxj.totalPrice", "");
        map.put("moldPartDxj.manufacturingFee", "");

        map.put("moldPartDgm.lengthOfPart", "");
        map.put("moldPartDgm.widthOfPart", "");
        map.put("moldPartDgm.heightOfPart", "");
        map.put("moldPartDgm.densityOfPart", "");
        map.put("moldPartDgm.weightOfPart", "");
        map.put("moldPartDgm.countOfPart", "");
        map.put("moldPartDgm.priceOfPart", "");
        map.put("moldPartDgm.totalPrice", "");
        map.put("moldPartDgm.manufacturingFee", "");
        map.put("moldPartDgm.totalStandardComponentCost", "");

        map.put("moldPartDxd.lengthOfPart", "");
        map.put("moldPartDxd.widthOfPart", "");
        map.put("moldPartDxd.heightOfPart", "");
        map.put("moldPartDxd.densityOfPart", "");
        map.put("moldPartDxd.weightOfPart", "");
        map.put("moldPartDxd.countOfPart", "");
        map.put("moldPartDxd.priceOfPart", "");
        map.put("moldPartDxd.totalPrice", "");
        map.put("moldPartDxd.manufacturingFee", "");
        map.put("moldPartDxd.totalStandardComponentCost", "");

        map.put("moldPartDhk.lengthOfPart", "");
        map.put("moldPartDhk.widthOfPart", "");
        map.put("moldPartDhk.heightOfPart", "");
        map.put("moldPartDhk.densityOfPart", "");
        map.put("moldPartDhk.weightOfPart", "");
        map.put("moldPartDhk.countOfPart", "");
        map.put("moldPartDhk.priceOfPart", "");
        map.put("moldPartDhk.totalPrice", "");
        map.put("moldPartDhk.manufacturingFee", "");
        map.put("moldPartDhk.totalStandardComponentCost", "");

        map.put("moldPartDtk.lengthOfPart", "");
        map.put("moldPartDtk.widthOfPart", "");
        map.put("moldPartDtk.heightOfPart", "");
        map.put("moldPartDtk.densityOfPart", "");
        map.put("moldPartDtk.weightOfPart", "");
        map.put("moldPartDtk.countOfPart", "");
        map.put("moldPartDtk.priceOfPart", "");
        map.put("moldPartDtk.totalPrice", "");
        map.put("moldPartDtk.manufacturingFee", "");
        map.put("moldPartDtk.totalStandardComponentCost", "");

        map.put("ironMaterialXxd.count", "");
        map.put("ironMaterialXxd.price", "");
        map.put("ironMaterialXxd.materialTotalPrice", "");
        map.put("ironMaterialXxd.processPrice", "");
        map.put("ironMaterialXxd.totalProcessPrice", "");
        map.put("ironMaterialXxd.standardComponent", "");
        map.put("ironMaterialXxd.totalStandardComponentCost", "");

        map.put("ironMaterialXzd.count", "");
        map.put("ironMaterialXzd.price", "");
        map.put("ironMaterialXzd.materialTotalPrice", "");
        map.put("ironMaterialXzd.processPrice", "");
        map.put("ironMaterialXzd.totalProcessPrice", "");
        map.put("ironMaterialXzd.standardComponent", "");
        map.put("ironMaterialXzd.totalStandardComponentCost", "");

        map.put("ironMaterialtk.count", "");
        map.put("ironMaterialtk.price", "");
        map.put("ironMaterialtk.materialTotalPrice", "");
        map.put("ironMaterialtk.processPrice", "");
        map.put("ironMaterialtk.totalProcessPrice", "");
        map.put("ironMaterialtk.standardComponent", "");
        map.put("ironMaterialtk.totalStandardComponentCost", "");

        map.put("tryoutFee.deviceName", "");
        map.put("tryoutTimes", "");
        map.put("imageFile", "");
        map.put("outsourceFee", "");
    }

}
